#include "GlobalHead.h"
# include <Shlobj.h>
#include "App_Application.h"
#include <Base/Interpreter.h>
#include "base/BaseClass.h"
#include "base/Type.h"
#include "base/Parameter.h"
#include <Base/FileInfo.h>

#include <boost/tokenizer.hpp>
#include <boost/token_functions.hpp>
#include <boost/signals.hpp>
#include <boost/bind.hpp>
#include <boost/version.hpp>

#include "App/Document.h"
#include "App/sceneObject.h"
#include "PropertyStandard.h"
#include "DocumentObjectGroup.h"
#include "DocumentObject.h"
#include "PropertyFile.h"
#include "VRMLObject.h"
#include "Tools.h"
#include <Base/UnitsApi.h>
#include "CustomPlayer.h"
#include "base/Console.h"
#include "part/AppPart.h"
#include "CompleteApp.h"
#include "DWGImport/DWGImporter.h"

using namespace App;
using namespace std;
using namespace boost;
using namespace boost::program_options;
using namespace Base;


ParameterManager* App_Application::_pcSysParamMngr = NULL;
ParameterManager* App_Application::_pcUserParamMngr = NULL;

std::map<std::string,std::string> App_Application::mConfig;


void segmentation_fault_handler(int sig)
{
	switch (sig) {
		case SIGSEGV:
			std::cerr << "Illegal storage access..." << std::endl;
			break;
		case SIGABRT:
			std::cerr << "Abnormal program termination..." << std::endl;
			break;
		default:
			std::cerr << "Unknown error occurred..." << std::endl;
			break;
	}

#if defined(__GNUC__)
	// According to the documentation to C signals we should exit.
	exit(3);
#endif
}

void unhandled_exception_handler()
{
	std::cerr << "Unhandled exception..." << std::endl;
}

void unexpection_error_handler()
{
	std::cerr << "Unexpected error occurred..." << std::endl;
	terminate();
}



App_Application* App_Application::_pcSingleton = 0;
App_Application::App_Application(ParameterManager *pcSysParamMngr, ParameterManager *pcUserParamMngr,std::map<std::string,std::string> &mConfigoid)
: _mConfig(mConfig)
{
	mpcPramManager["System parameter"] = _pcSysParamMngr;
	mpcPramManager["User parameter"] = _pcUserParamMngr;

// 	addImportType("Inventor V2.1 (*.iv)","FreeCADGui");
 	addImportType("VRML V2.0 (*.wrl *.vrml *.wrz *.wrl.gz)","FreeCADGui");
 	addImportType("DCityIm (*.nmo)","DigtalCity");
	addImportType("DCity (*.cmo)","digtalCity");
//    addExportType("Inventor V2.1 (*.iv)","FreeCADGui");
// 	addExportType("VRML V2.0 (*.wrl *.vrml *.wrz *.wrl.gz)","FreeCADGui");
//    addExportType("IDTF (for 3D PDF) (*.idtf)","FreeCADGui");
// 	addExportType("3D View (*.svg)","FreeCADGui");
}

App_Application::~App_Application(void)
{
}

bool App_Application::closeDocument(const char* name)
{
	map<string,Document*>::iterator pos = DocMap.find( name );
	if (pos == DocMap.end()) // no such document
		return false;

	// Trigger observers before removing the document from the internal map.
	// Some observers might rely on that this document is still there.
	signalDeleteDocument(*pos->second);

	// For exception-safety use a smart pointer
	if (_pActiveDoc == pos->second)
		setActiveDocument((Document*)0);
	auto_ptr<Document> delDoc (pos->second);
	DocMap.erase( pos );

	// Trigger observers after removing the document from the internal map.
	signalDeletedDocument();

	return true;
}

void App_Application::closeAllDocuments(void)
{
	std::map<std::string,Document*>::iterator pos;
	while((pos = DocMap.begin()) != DocMap.end())
		closeDocument(pos->first.c_str());
}



Document* App_Application::getActiveDocument(void) const
{
	return _pActiveDoc;
}

std::vector<App::Document*> App_Application::getDocuments() const
{
	std::vector<App::Document*> docs;
	for (std::map<std::string,Document*>::const_iterator it = DocMap.begin(); it != DocMap.end(); ++it)
		docs.push_back(it->second);
	return docs;
}
App::Document* App_Application::getDocument(const char *Name) const
{
	std::map<std::string,Document*>::const_iterator pos;

	pos = DocMap.find(Name);

	if (pos == DocMap.end())
		return 0;

	return pos->second;
}

const char * App_Application::getDocumentName(const App::Document* doc) const
{
	for (std::map<std::string,Document*>::const_iterator it = DocMap.begin(); it != DocMap.end(); ++it)
		if (it->second == doc)
			return it->first.c_str();

	return 0;
}


void App_Application::destruct(void)
{
	// saving system parameter
//	Console().Log("Saving system parameter...\n");
	_pcSysParamMngr->SaveDocument(mConfig["SystemParameter"].c_str());
	// saving the User parameter
//	Console().Log("Saving system parameter...done\n");
//	Console().Log("Saving user parameter...\n");
	_pcUserParamMngr->SaveDocument(mConfig["UserParameter"].c_str());
//	Console().Log("Saving user parameter...done\n");
	// clean up
	delete _pcSysParamMngr;
	delete _pcUserParamMngr;

	// not initialized or doubel destruct!
	assert(_pcSingleton);
	delete _pcSingleton;
	
	// We must detach from console and delete the observer to save our file
	destructObserver();

	//Base::Interpreter().finalize();

	//ScriptFactorySingleton::Destruct();
	InterpreterSingleton::Destruct();
	CompleteApp::destruct();
	ConsoleSingleton::Destruct();
	CCustomPlayer::destruct();
	DWGImporter::destruct();
	Base::Type::destruct();
}
void App_Application::destructObserver(void)
{
// 	if ( _pConsoleObserverFile ) {
// 		Console().DetachObserver(_pConsoleObserverFile);
// 		delete _pConsoleObserverFile;
// 		_pConsoleObserverFile = 0;
// 	}
// 	if ( _pConsoleObserverStd ) {
// 		Console().DetachObserver(_pConsoleObserverStd);
// 		delete _pConsoleObserverStd;
// 		_pConsoleObserverFile = 0;
// 	}
}



void App_Application::init()
{

//#ifdef _MSC_VER // Microsoft compiler
//	_set_new_handler ( freecadNewHandler ); // Setup new handler
//	_set_new_mode( 1 ); // Re-route malloc failures to new handler !
//#else   // Ansi compiler
//	std::set_new_handler (freecadNewHandler); // ANSI new handler
//#endif
	// if an unexpected crash occurs we can install a handler function to
	// write some additional information
	std::signal(SIGSEGV,segmentation_fault_handler);
	std::signal(SIGABRT,segmentation_fault_handler);
	std::set_terminate(unhandled_exception_handler);
	std::set_unexpected(unexpection_error_handler);

	initTypes();

	boost::filesystem::path::default_name_check(boost::filesystem::no_check);

	initConfig();
	initApplication();

}

void App_Application::initConfig()
{
	mConfig["AppHomePath"] = FindHomePath();

// 	if (App_Application::Config().find("BuildVersionMajor") == App::Application::Config().end()) {
// 		std::stringstream str; str << FCVersionMajor << "." << FCVersionMinor;
// 		App_Application::Config()["ExeVersion"]         = str.str();
// 		App_Application::Config()["BuildVersionMajor"]  = FCVersionMajor;
// 		App_Application::Config()["BuildVersionMinor"]  = FCVersionMinor;
// 		App_Application::Config()["BuildRevision"]      = FCRevision;
// 		App_Application::Config()["BuildRepositoryURL"] = FCRepositoryURL;
// 		App_Application::Config()["BuildRevisionDate"]  = FCCurrentDateT;
// 	}

	ExtractUserPath();
#   ifdef FC_DEBUG
	mConfig["Debug"] = "1";
#   else
	mConfig["Debug"] = "0";
#   endif

   LoadParameters();

     UnitsApi::setDefaults();

	 // capture path
	 SaveEnv("PATH");
	 logStatus();
}
void App_Application::SaveEnv(const char* s)
{
	char *c = getenv(s);
	if (c)
		mConfig[s] = c;
}

void App_Application::logStatus()
{
	time_t now;
	time(&now);
	Console().Log("Time = %s", ctime(&now));

	for (std::map<std::string,std::string>::iterator It = mConfig.begin();It!= mConfig.end();It++) {
		Console().Log("%s = %s\n",It->first.c_str(),It->second.c_str());
	}
}


void App_Application::LoadParameters()
{
	// create standard parameter sets
	_pcSysParamMngr = new ParameterManager();
	_pcUserParamMngr = new ParameterManager();

	if (mConfig.find("UserParameter") == mConfig.end())
		mConfig["UserParameter"]   = mConfig["UserAppData"] + "user.cfg";
	if (mConfig.find("SystemParameter") == mConfig.end())
		mConfig["SystemParameter"] = mConfig["UserAppData"] + "system.cfg";

	_pcSysParamMngr->LoadOrCreateDocument(mConfig["SystemParameter"].c_str());
	_pcUserParamMngr->LoadOrCreateDocument(mConfig["UserParameter"].c_str());
}

void App_Application::ExtractUserPath()
{
	WCHAR szPath[MAX_PATH];
	TCHAR dest[MAX_PATH*3];
	// Get the default path where we can save our documents. It seems that
	// 'CSIDL_MYDOCUMENTS' doesn't work on all machines, so we use 'CSIDL_PERSONAL'
	// which does the same.
	if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, szPath))) {
		WideCharToMultiByte(CP_UTF8, 0, szPath, -1,dest, 256, NULL, NULL);
		mConfig["UserHomePath"] = dest;
	}
	else
		mConfig["UserHomePath"] = mConfig["AppHomePath"];

	// In the second step we want the directory where user settings of the application can be
	// kept. There we create a directory with name of the vendor and a sub-directory with name
	// of the application.
	if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, szPath))) {
		// convert to UTF8
		WideCharToMultiByte(CP_UTF8, 0, szPath, -1,dest, 256, NULL, NULL);

		std::string appData = dest;
		Base::FileInfo fi(appData.c_str());
		if (!fi.exists()) {
			// This should never ever happen
			std::stringstream str;
			str << "Application data directory " << appData << " does not exist!";
		//	throw Base::Exception(str.str());
		}

		// Try to write into our data path, therefore we must create some directories, first.
		// If 'AppDataSkipVendor' is defined the value of 'ExeVendor' must not be part of
		// the path.
		if (mConfig.find("AppDataSkipVendor") == mConfig.end()) {
			appData += PATHSEP;
			appData += mConfig["ExeVendor"];
			fi.setFile(appData.c_str());
			if (!fi.exists()/* && !Py_IsInitialized()*/) {
				if (!fi.createDirectory()) {
					std::string error = "Cannot create directory ";
					error += appData;
					// Want more details on console
					std::cerr << error << std::endl;
					//throw Base::Exception(error);
				}
			}
		}

		appData += PATHSEP;
		appData += mConfig["ExeName"];
		fi.setFile(appData.c_str());
		if (!fi.exists()/* && !Py_IsInitialized()*/) {
			if (!fi.createDirectory()) {
				std::string error = "Cannot create directory ";
				error += appData;
				// Want more details on console
				std::cerr << error << std::endl;
				//throw Base::Exception(error);
			}
		}

		// Actually the name of the directory where the parameters are stored should be the name of
		// the application due to branding reasons.
		appData += PATHSEP;
		mConfig["UserAppData"] = appData;
	}
}
void App_Application::initApplication()
{
	App_Application::_pcSingleton = new App_Application(0,0,mConfig);

}
// const char* App_Application::getExecutableName(void)const
// {
// 	return _mConfig["ExeName"].c_str();
// }

void App_Application::initTypes()
{
	Base::Type                      ::init();
	Base::BaseClass                 ::init();
//	Base::Exception                 ::init();
	Base::Persistence               ::init();

	// Complex data classes
	Data::ComplexGeoData            ::init();
	//Data::Segment                   ::init();

	// Properties
	App ::Property                  ::init();
	App ::PropertyContainer         ::init();
	App ::PropertyLists             ::init();
	App ::PropertyBool              ::init();
	App ::PropertyFloat             ::init();
	App ::PropertyFloatList         ::init();
	App ::PropertyFloatConstraint   ::init();
	App ::PropertyAngle             ::init();
	App ::PropertyDistance          ::init();
	App ::PropertyLength            ::init();
	App ::PropertySpeed             ::init();
	App ::PropertyAcceleration      ::init();
	App ::PropertyInteger           ::init();
	App ::PropertyIntegerConstraint ::init();
	App ::PropertyPercent           ::init();
	App ::PropertyEnumeration       ::init();
	App ::PropertyIntegerList       ::init();
	App ::PropertyString            ::init();
	App ::PropertyFont              ::init();
	App ::PropertyStringList        ::init();
	App ::PropertyLink              ::init();
	App ::PropertyLinkSub           ::init();
	App ::PropertyLinkList          ::init();
	App ::PropertyLinkSubList       ::init();
	App ::PropertyMatrix            ::init();
	App ::PropertyVector            ::init();
	App ::PropertyVectorList        ::init();
	App ::PropertyPlacement         ::init();
	App ::PropertyPlacementLink     ::init();
	App ::PropertyGeometry          ::init();
	App ::PropertyComplexGeoData    ::init();
	App ::PropertyColor             ::init();
	App ::PropertyColorList         ::init();
	App ::PropertyMaterial          ::init();
	App ::PropertyPath              ::init();
	App ::PropertyFile              ::init();
	App ::PropertyFileIncluded      ::init();
//	App ::PropertyPythonObject      ::init();
	// Document classes
	App ::DocumentObject            ::init();
	App ::GeoFeature                ::init();
// 	App ::FeatureTest               ::init();
// 	App ::FeatureTestException      ::init();
// 	App ::FeaturePython             ::init();
// 	App ::GeometryPython            ::init();
	App ::Document                  ::init();
	App ::DocumentObjectGroup       ::init();
// 	App ::DocumentObjectGroupPython ::init();
// 	App ::DocumentObjectFileIncluded::init();
 //	App ::InventorObject            ::init();
 	App ::VRMLObject                ::init();
// 	App ::Annotation                ::init();
// 	App ::AnnotationLabel           ::init();
// 	App ::MeasureDistance           ::init();

//	CompleteApp::Instance()->InitCompleteApp();
	//AppPart::Instance()->initPart();
	App::CompleteApp::Instance()->InitCompleteApp();





	
}
ParameterManager * App_Application::GetParameterSet(const char* sName) const
{
	std::map<std::string,ParameterManager *>::const_iterator it = mpcPramManager.find(sName);
	if ( it != mpcPramManager.end() )
		return it->second;
	else
		return 0;
}

const std::map<std::string,ParameterManager *> & App_Application::GetParameterSetList(void) const
{
	return mpcPramManager;
}

void App_Application::AddParameterSet(const char* sName)
{

}
void App_Application::RemoveParameterSet(const char* sName)
{

}


void App_Application::addObject(const char * objectName)
{
	GetApp_Application().getActiveDocument()->addObject("Part::sceneObject",objectName);
}
Document* App_Application::openDocument(const char * FileName)
{
	FileInfo File(FileName);

	if (!File.exists()) {
		//std::stringstream str;
		//str << "File '" << FileName << "' does not exist!";
		//throw Base::Exception(str.str().c_str());

		return NULL;
	}

	// Before creating a new document we check whether the document is already open
// 	std::string filepath = File.filePath();
// 	for (std::map<std::string,Document*>::iterator it = DocMap.begin(); it != DocMap.end(); ++it) {
// 		// get unique path separators
// 		std::string fi = FileInfo(it->second->FileName.getValue()).filePath();
// 		if (filepath != fi) {
// // 			std::stringstream str;
// // 			str << "The project '" << FileName << "' is already open!";
// // 			throw Base::Exception(str.str().c_str());
// 
// 			return NULL;
// 		}
// 	}

	// Use the same name for the internal and user name.
	// The file name is UTF-8 encoded which means that the internal name will be modified
	// to only contain valid ASCII characters but the user name will be kept.
	Document* newDoc = getActiveDocument();//newDocument(File.fileNamePure().c_str(), File.fileNamePure().c_str());
     
	newDoc->FileName.setValue(File.filePath());

	// read the document
	newDoc->restore();

	return newDoc;
}
void App_Application::openDocument_s(const char * FileName)
{
	GetApp_Application().openDocument(FileName);
}


Base::Reference<ParameterGrp>  App_Application::GetParameterGroupByPath(const char* sName)
{
	std::string cName = sName,cTemp;

	std::string::size_type pos = cName.find(':');

	// is there a path seperator ?
	if (pos == std::string::npos) {
		//throw Base::Exception("Application::GetParameterGroupByPath() no parameter set name specified");
	}
	// assigning the parameter set name
	cTemp.assign(cName,0,pos);	
	cName.erase(0,pos+1);

	// test if name is valid
	std::map<std::string,ParameterManager *>::iterator It = mpcPramManager.find(cTemp.c_str());
	if (It == mpcPramManager.end())
	{
	}
		//throw Base::Exception("Application::GetParameterGroupByPath() unknown parameter set name specified");

	return It->second->GetGroup(cName.c_str());
}

void  App_Application::newDocument_S(const char * Name, const char * UserName)
{
	GetApp_Application().signalNewScene(*(GetApp_Application()._pActiveDoc));
}

void App_Application::setActiveDocument(App::Document* pDoc)
{
//    _pActiveDoc = pDoc;
// 
//    if (pDoc)
// 	   signalActiveDocument(*pDoc);
}
void App_Application::setActiveDocument(const char *Name)
{

}
void App_Application::importObject(const char * Name, const char * UserName)
{
	const char* DocName = 0;
	QString fileName = QString::fromUtf8(Name);
	QFileInfo fi;
	fi.setFile(fileName);
	QString ext = fi.completeSuffix().toLower();
	if(ext == QLatin1String("nmo"))	
	{
		App::Document* doc = 0;
		doc = GetApp_Application().getActiveDocument();

		App::DocumentObject* obj = doc->addObject("Part::sceneObject",
			(const char*)fi.baseName().toUtf8()/*,so*/);
		obj->Label.setValue((const char*)fi.baseName().toUtf8());
		obj->pathName.setValue((const char*)fi.absoluteFilePath().toUtf8());

		obj->setAsImport();
// 		static_cast<App::PropertyFileIncluded*>(obj->getPropertyByName("VrmlFile"))
// 			->setValue((const char*)fi.absoluteFilePath().toUtf8());
		
		// GetApp_Application().signalUpdataDoumentObject(*obj);
		 doc->recompute();
		 obj->finshImport();
	}

}

std::string App_Application::getUniqueDocumentName(const char *Name) const
{
	if (!Name || *Name == '\0')
		return std::string();
	std::string CleanName = Base::Tools::getIdentifier(Name);

	// name in use?
	std::map<string,Document*>::const_iterator pos;
	pos = DocMap.find(CleanName);

	if (pos == DocMap.end()) {
		// if not, name is OK
		return CleanName;
	}
	else {
		std::vector<std::string> names;
		names.reserve(DocMap.size());
		for (pos = DocMap.begin();pos != DocMap.end();++pos) {
			names.push_back(pos->first);
		}
		return Base::Tools::getUniqueName(CleanName, names);
	}
}
// void App_Application::resetDocument_S(const char * Name, const char * UserName)
// {
//      GetApp_Application().resetDocument();
// }
// 
// bool App_Application::resetDocument()
// {
// 	map<string,Document*>::iterator pos = DocMap.find( "Unnamed" );
// 	if (pos == DocMap.end()) // no such document
// 		return false;
// 
// 	if (!pos->second->isClosable())
// 		return false;
// 
//      signalResetDocument(*pos->second);
// 	 // signalDeleteDocument(*pos->second);
// 	 // signalDeletedDocument();
//     return true;
// }
App::Document* App_Application::newDocument(const char * Name, const char * UserName)
{
	// get anyway a valid name!
  	if (!Name || Name[0] == '\0')
  		Name = "Unnamed";
  	string name = getUniqueDocumentName(Name);
 
 	// create the FreeCAD document
	auto_ptr<App::Document> newDoc(new App::Document() );
// 
// 	// add the document to the internal list
  	DocMap[Name] = newDoc.release(); // now owned by the Application
  	_pActiveDoc = DocMap[Name];
// // 
// // 
// // 	// connect the signals to the application for the new document
  	_pActiveDoc->signalNewObject.connect(boost::bind(&App_Application::slotNewObject, this, _1));
  	_pActiveDoc->signalDeletedObject.connect(boost::bind(&App_Application::slotDeletedObject, this, _1));
  	_pActiveDoc->signalChangedObject.connect(boost::bind(&App_Application::slotChangedObject, this, _1, _2));
  	_pActiveDoc->signalRenamedObject.connect(boost::bind(&App_Application::slotRenamedObject, this, _1));
  	_pActiveDoc->signalActivatedObject.connect(boost::bind(&App_Application::slotActivatedObject, this, _1));
// 
// 	// make sure that the active document is set in case no GUI is up
// 	{
// 		Base::PyGILStateLocker lock;
// 		Py::Object active(_pActiveDoc->getPyObject(), true);
// 		Py::Module("FreeCAD").setAttr(std::string("ActiveDocument"),active);
// 	}
// 
 	signalNewDocument(*_pActiveDoc);
// 
 	// set the UserName after notifying all observers
  	if (UserName)
  		_pActiveDoc->Label.setValue(UserName);
  	else
  		_pActiveDoc->Label.setValue(name);
 
 	return _pActiveDoc;

}



//**************************************************************************
// signaling
void App_Application::slotNewObject(const App::DocumentObject&O)
{
    this->signalNewObject(O);
}

void App_Application::slotDeletedObject(const App::DocumentObject&O)
{
    this->signalDeletedObject(O);
}

void App_Application::slotChangedObject(const App::DocumentObject&O, const App::Property& P)
{
    this->signalChangedObject(O,P);
}

void App_Application::slotRenamedObject(const App::DocumentObject&O)
{
    this->signalRenamedObject(O);
}

void App_Application::slotActivatedObject(const App::DocumentObject&O)
{
    this->signalActivatedObject(O);
}


void App_Application::addImportType(const char* Type, const char* ModuleName)
{
	FileTypeItem item;
	item.filter = Type;
	item.module = ModuleName;

	// Extract each filetype from 'Type' literal
	std::string::size_type pos = item.filter.find("*.");
	while ( pos != std::string::npos ) {
		std::string::size_type next = item.filter.find_first_of(" )", pos+1);
		std::string::size_type len = next-pos-2;
		std::string type = item.filter.substr(pos+2,len);
		item.types.push_back(type);
		pos = item.filter.find("*.", next);
	}

	// Due to branding stuff replace FreeCAD through the application name
	if (strncmp(Type, "FreeCAD", 7) == 0) {
		std::string AppName = Config()["ExeName"];
		AppName += item.filter.substr(7);
		item.filter = AppName;
		// put to the front of the array
		_mImportTypes.insert(_mImportTypes.begin(),item);
	}
	else {
		_mImportTypes.push_back(item);
	}
}

std::vector<std::string> App_Application::getImportTypes(const char* Module) const
{
	std::vector<std::string> types;
 	for (std::vector<FileTypeItem>::const_iterator it = _mImportTypes.begin(); it != _mImportTypes.end(); ++it) {

 		if (_stricmp(Module,it->module.c_str()) == 0)

 			types.insert(types.end(), it->types.begin(), it->types.end());
 	}

	return types;
}

std::vector<std::string> App_Application::getImportTypes(void) const
{
	std::vector<std::string> types;
 	for (std::vector<FileTypeItem>::const_iterator it = _mImportTypes.begin(); it != _mImportTypes.end(); ++it) {
 		types.insert(types.end(), it->types.begin(), it->types.end());
 	}
 
 	std::sort(types.begin(), types.end());
 	types.erase(std::unique(types.begin(), types.end()), types.end());

	return types;
}


std::map<std::string, std::string> App_Application::getImportFilters(const char* Type) const
{
	std::map<std::string, std::string> moduleFilter;
 	for (std::vector<FileTypeItem>::const_iterator it = _mImportTypes.begin(); it != _mImportTypes.end(); ++it) {
 		const std::vector<std::string>& types = it->types;
 		for (std::vector<std::string>::const_iterator jt = types.begin(); jt != types.end(); ++jt) {

 			if (_stricmp(Type,jt->c_str()) == 0)

 				moduleFilter[it->filter] = it->module;
 		}
 	}

	return moduleFilter;
}

std::map<std::string, std::string> App_Application::getImportFilters(void) const
{
	std::map<std::string, std::string> filter;
 	for (std::vector<FileTypeItem>::const_iterator it = _mImportTypes.begin(); it != _mImportTypes.end(); ++it) {
 		filter[it->filter] = it->module;
 	}

	return filter;
}


std::vector<std::string> App_Application::getExportTypes(const char* Module) const
{
	std::vector<std::string> types;
 	for (std::vector<FileTypeItem>::const_iterator it = _mExportTypes.begin(); it != _mExportTypes.end(); ++it) {

 		if (_stricmp(Module,it->module.c_str()) == 0)
 			types.insert(types.end(), it->types.begin(), it->types.end());
 	}

	return types;
}

std::vector<std::string> App_Application::getExportTypes(void) const
{
	std::vector<std::string> types;
 	for (std::vector<FileTypeItem>::const_iterator it = _mExportTypes.begin(); it != _mExportTypes.end(); ++it) {
 		types.insert(types.end(), it->types.begin(), it->types.end());
 	}
 
 	std::sort(types.begin(), types.end());
 	types.erase(std::unique(types.begin(), types.end()), types.end());

	return types;
}


std::map<std::string, std::string> App_Application::getExportFilters(const char* Type) const
{
	std::map<std::string, std::string> moduleFilter;
 	for (std::vector<FileTypeItem>::const_iterator it = _mExportTypes.begin(); it != _mExportTypes.end(); ++it) {
 		const std::vector<std::string>& types = it->types;
 		for (std::vector<std::string>::const_iterator jt = types.begin(); jt != types.end(); ++jt) {

 			if (_stricmp(Type,jt->c_str()) == 0)
 				moduleFilter[it->filter] = it->module;
 		}
 	}

	return moduleFilter;
}

std::map<std::string, std::string> App_Application::getExportFilters(void) const
{
	std::map<std::string, std::string> filter;
 	for (std::vector<FileTypeItem>::const_iterator it = _mExportTypes.begin(); it != _mExportTypes.end(); ++it) {
 		filter[it->filter] = it->module;
 	}

	return filter;
}

std::string App_Application::FindHomePath()
{
	// We have three ways to start this application either use one of the both executables or
	// import the FreeCAD.pyd module from a running Python session. In the latter case the
	// Python interpreter is already initialized.
	char  szFileName [MAX_PATH] ;
	GetModuleFileName(0, szFileName, MAX_PATH-1);
	std::string Call(szFileName), TempHomePath;
	std::string::size_type pos = Call.find_last_of(PATHSEP);
	TempHomePath.assign(Call,0,pos);
	pos = TempHomePath.find_last_of(PATHSEP);
	TempHomePath.assign(TempHomePath,0,pos+1);

	// switch to posix style
	for (std::string::iterator i=TempHomePath.begin();i!=TempHomePath.end();++i) {
		if (*i == '\\')
			*i = '/';
	}

	return TempHomePath;
}



const char* App_Application::GetHomePath(void) const
{
	return _mConfig["AppHomePath"].c_str();
}

const char* App_Application::getExecutableName(void) const
{
	return _mConfig["ExeName"].c_str();
}

std::string App_Application::getUserAppDataDir()
{
	return mConfig["UserAppData"];
}

std::string App_Application::getResourceDir()
{
#ifdef RESOURCEDIR
	std::string path(RESOURCEDIR);
	path.append("/");
	QDir dir(QString::fromUtf8(RESOURCEDIR));
	if (dir.isAbsolute())
		return path;
	else
		return mConfig["AppHomePath"] + path;
#else
	return mConfig["AppHomePath"];
#endif
}

std::string App_Application::getHelpDir()
{
#ifdef DOCDIR
	std::string path(DOCDIR);
	path.append("/");
	QDir dir(QString::fromUtf8(DOCDIR));
	if (dir.isAbsolute())
		return path;
	else
		return mConfig["AppHomePath"] + path;
#else
	return mConfig["DocPath"];
#endif
}



 ParameterManager & App_Application::GetUserParameter(void)
 {
 	return *_pcUserParamMngr;
 }
 ParameterManager & App_Application::GetSystemParameter(void)
 {
 	return *_pcSysParamMngr;
 }





